﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using CarbonExchange.Bll;

namespace CarbonExchange.Tests
{
    [TestClass]
    public class TemplateControlTests : BaseTest
    {
        [TestMethod]
        public void TemplateControl_GetById_WithIncorrectId_ReturnsNull()
        {
            TemplateControlFactory factory = new TemplateControlFactory(_Context);
            Assert.IsNull(factory.GetById(int.MaxValue));
        }

        [TestMethod]
        public void TemplateControl_GetById_WithCorrectId_ReturnsNotNull()
        {
            TemplateControlFactory factory = new TemplateControlFactory(_Context);
            Assert.IsNotNull(factory.GetById(_TestTemplateControls[1].Id));
        }

        [TestMethod]
        public void TemplateControl_GetById_WithCorrectId_PopulatesCorrectly()
        {
            TemplateControlFactory factory = new TemplateControlFactory();
            var i = 1;
            var tmp = factory.GetById(_TestTemplateControls[i].Id);
            Assert.IsNotNull(tmp);
            Assert.AreEqual(_TestTemplateControls[i].Id, tmp.Id);
            Assert.AreEqual(_TestTemplateControls[i].TemplateControlType.AdminDisplayControlType, tmp.AdminDisplayControlType);
            Assert.AreEqual(_TestTemplateControls[i].TemplateControlType.AdminEditControlType, tmp.AdminEditControlType);
            Assert.AreEqual(_TestTemplateControls[i].TemplateControlType.FrontEndControlType, tmp.FrontEndControlType);
            Assert.AreEqual(_TestTemplateControls[i].CID, tmp.CID);
            Assert.AreEqual(_TestTemplateControls[i].Name, tmp.Name);
            Assert.AreEqual(_TestTemplateControls[i].Notes, tmp.Notes);
            Assert.AreEqual(_TestTemplateControls[i].Sequence, tmp.Sequence);
            Assert.AreEqual(_TestTemplateControls[i].TemplateControlTypeId, tmp.TemplateControlTypeId);
            Assert.AreEqual(_TestTemplateControls[i].TemplateControlType.Name, tmp.TemplateControlTypeName);
            Assert.AreEqual(_TestTemplateControls[i].TemplateId, tmp.TemplateId);
        }

        [TestMethod]
        public void TemplateControl_GetAllByTemplateId_WithIncorrectId_ReturnsEmptyList()
        {
            TemplateControlFactory factory = new TemplateControlFactory(_Context);
            Assert.AreEqual(0, factory.GetAllByTemplateId(int.MaxValue).Count());
        }

        [TestMethod]
        public void TemplateControl_GetAllByTemplateId_WithCorrectId_ReturnsNotNull()
        {
            TemplateControlFactory factory = new TemplateControlFactory(_Context);
            Assert.AreEqual(_TestTemplateControls.Count(), factory.GetAllByTemplateId(_TestTemplates[0].Id).Count());
        }

        [TestMethod]
        public void TemplateControl_GetAllByTemplateId_WithCorrectId_PopulatesCorrectly()
        {
            TemplateControlFactory factory = new TemplateControlFactory();
            var tmpList = factory.GetAllByTemplateId(_TestTemplates[0].Id).ToList();
            Assert.IsNotNull(tmpList);
            Assert.AreEqual(_TestTemplateControls.Count(), tmpList.Count());
            int i = 0;
            foreach (var tmp in tmpList)
            {
                Assert.AreEqual(_TestTemplateControls[i].Id, tmp.Id);
                Assert.AreEqual(_TestTemplateControls[i].TemplateControlType.AdminDisplayControlType, tmp.AdminDisplayControlType);
                Assert.AreEqual(_TestTemplateControls[i].TemplateControlType.AdminEditControlType, tmp.AdminEditControlType);
                Assert.AreEqual(_TestTemplateControls[i].TemplateControlType.FrontEndControlType, tmp.FrontEndControlType);
                Assert.AreEqual(_TestTemplateControls[i].CID, tmp.CID);
                Assert.AreEqual(_TestTemplateControls[i].Name, tmp.Name);
                Assert.AreEqual(_TestTemplateControls[i].Notes, tmp.Notes);
                Assert.AreEqual(_TestTemplateControls[i].Sequence, tmp.Sequence);
                Assert.AreEqual(_TestTemplateControls[i].TemplateControlTypeId, tmp.TemplateControlTypeId);
                Assert.AreEqual(_TestTemplateControls[i].TemplateControlType.Name, tmp.TemplateControlTypeName);
                Assert.AreEqual(_TestTemplateControls[i].TemplateId, tmp.TemplateId);
                i++;
            }
        }

        [TestMethod]
        public void TemplateControl_DeleteOne()
        {
            TemplateControlFactory factory = new TemplateControlFactory(_Context);
            var tmp = factory.GetById(_TestTemplateControls[0].Id);
            Assert.IsNotNull(tmp);
            factory.Delete(tmp);
            Assert.IsNull(factory.GetById(_TestTemplateControls[0].Id));
            Assert.AreEqual(_TestTemplateControls.Count - 1, factory.GetAllByTemplateId(_TestTemplates[0].Id).Count());
        }

        [TestMethod]
        public void TemplateControl_DeleteMany()
        {
            TemplateControlFactory factory = new TemplateControlFactory(_Context);
            var tmp = factory.GetAllByTemplateId(_TestTemplates[0].Id);
            Assert.IsTrue(tmp.Count() > 0);
            factory.Delete(tmp);
            Assert.IsNull(factory.GetById(_TestTemplateControls[0].Id));
            Assert.AreEqual(0, factory.GetAllByTemplateId(_TestTemplates[0].Id).Count());
        }

        [TestMethod]
        public void TemplateControl_UpdateOne()
        {
            TemplateControlFactory factory = new TemplateControlFactory(_Context);
            var tmp = factory.GetById(_TestTemplateControls[0].Id);
            Assert.IsNotNull(tmp);

            tmp.Name = "Update Name";
            tmp.Notes = "Update Notes";

            var cid = tmp.CID;

            factory.Save(tmp);

            Assert.AreEqual(_TestTemplateControls[0].Id, tmp.Id);
            Assert.AreEqual("Acms.AdminDisplayControlType0", tmp.AdminDisplayControlType);
            Assert.AreEqual("Acms.AdminEditControlType0", tmp.AdminEditControlType);
            Assert.AreEqual("Acms.FrontEndControlType0", tmp.FrontEndControlType);
            Assert.AreEqual("Update Name", tmp.Name);
            Assert.AreEqual("Update Notes", tmp.Notes);
            Assert.AreNotEqual(cid, tmp.CID);

            var tmp2 = factory.GetById(tmp.Id);

            Assert.AreEqual(tmp2.Id, tmp.Id);
            Assert.AreEqual(tmp2.AdminDisplayControlType, tmp.AdminDisplayControlType);
            Assert.AreEqual(tmp2.AdminEditControlType, tmp.AdminEditControlType);
            Assert.AreEqual(tmp2.FrontEndControlType, tmp.FrontEndControlType);
            Assert.AreEqual(tmp2.Name, tmp.Name);
            Assert.AreEqual(tmp2.Notes, tmp.Notes);
            Assert.AreEqual(tmp2.CID, tmp.CID);
        }

        [TestMethod]
        public void TemplateControl_UpdateMany()
        {
            TemplateControlFactory factory = new TemplateControlFactory(_Context);
            var tmpList = factory.GetAllByTemplateId(_TestTemplates[0].Id).ToList();

            Assert.IsNotNull(tmpList);

            object[] cids = new object[tmpList.Count()];
            int i = 0;
            foreach (var tmp in tmpList)
            {
                tmp.Name = "Update Name {0}".Format(i);
                tmp.Notes = "Update Notes {0}".Format(i);
                cids[i] = tmp.CID;
                i++;
            }

            factory.Save(tmpList);

            i = 0;
            foreach (var tmp in tmpList)
            {
                Assert.AreEqual(_TestTemplateControls[i].Id, tmp.Id);
                Assert.AreEqual("Acms.AdminDisplayControlType{0}".Format(i), tmp.AdminDisplayControlType);
                Assert.AreEqual("Acms.AdminEditControlType{0}".Format(i), tmp.AdminEditControlType);
                Assert.AreEqual("Acms.FrontEndControlType{0}".Format(i), tmp.FrontEndControlType);
                Assert.AreEqual("Update Name {0}".Format(i), tmp.Name);
                Assert.AreEqual("Update Notes {0}".Format(i), tmp.Notes);
                Assert.AreNotEqual(cids[i], tmp.CID);
                i++;
            }

            var tmpList2 = factory.GetAllByTemplateId(_TestTemplates[0].Id).ToArray();

            i = 0;

            foreach (var tmp in tmpList)
            {
                var tmp2 = tmpList2[i];

                Assert.AreEqual(tmp2.Id, tmp.Id);
                Assert.AreEqual(tmp2.AdminDisplayControlType, tmp.AdminDisplayControlType);
                Assert.AreEqual(tmp2.AdminEditControlType, tmp.AdminEditControlType);
                Assert.AreEqual(tmp2.FrontEndControlType, tmp.FrontEndControlType);
                Assert.AreEqual(tmp2.Name, tmp.Name);
                Assert.AreEqual(tmp2.Notes, tmp.Notes);
                Assert.AreEqual(tmp2.CID, tmp.CID);

                i++;
            }
        }

        [TestMethod]
        public void TemplateControl_InsertOne()
        {
            TemplateControlFactory factory = new TemplateControlFactory(_Context);
            var tmp = new TemplateControl(_TestTemplates[1].Id);

            tmp.TemplateControlTypeId = _TestTemplateControlTypes.Last().Id;
            tmp.Name = "Insert Name";
            tmp.Notes = "Insert Notes";

            factory.Save(tmp);

            Assert.AreEqual(_Context.TemplateControls.OrderByDescending(x => x.Id).First().Id, tmp.Id);
            Assert.AreEqual(_TestTemplateControlTypes.Last().AdminDisplayControlType, tmp.AdminDisplayControlType);
            Assert.AreEqual(_TestTemplateControlTypes.Last().AdminEditControlType, tmp.AdminEditControlType);
            Assert.AreEqual(_TestTemplateControlTypes.Last().FrontEndControlType, tmp.FrontEndControlType);
            Assert.AreEqual("Insert Name", tmp.Name);
            Assert.AreEqual("Insert Notes", tmp.Notes);
            Assert.AreEqual(0, tmp.Sequence);
            Assert.AreEqual(_Context.TemplateControls.OrderByDescending(x => x.Id).First().CID, tmp.CID);

            var tmp2 = factory.GetById(tmp.Id);
            Assert.AreEqual(tmp2.Id, tmp.Id);
            Assert.AreEqual(tmp2.AdminDisplayControlType, tmp.AdminDisplayControlType);
            Assert.AreEqual(tmp2.AdminEditControlType, tmp.AdminEditControlType);
            Assert.AreEqual(tmp2.FrontEndControlType, tmp.FrontEndControlType);
            Assert.AreEqual(tmp2.Name, tmp.Name);
            Assert.AreEqual(tmp2.Notes, tmp.Notes);
            Assert.AreEqual(tmp2.CID, tmp.CID);

            Assert.AreEqual(1, factory.GetAllByTemplateId(_TestTemplates[1].Id).Count());
        }

        [TestMethod]
        public void TemplateControl_InsertMany()
        {
            TemplateControlFactory factory = new TemplateControlFactory(_Context);
            int noToGen = 3;
            List<TemplateControl> tmpList = new List<TemplateControl>();
            for (int i = 0; i < noToGen; i++)
            {

                var tmp = new TemplateControl(_TestTemplates[1].Id);

                tmp.TemplateControlTypeId = _TestTemplateControlTypes[i % _TestTemplateControlTypes.Count].Id;
                tmp.Name = "Insert Name {0}".Format(i);
                tmp.Notes = "Insert Notes {0}".Format(i);

                tmpList.Add(tmp);
            }

            factory.Save(tmpList);

            for (int i = 0; i < noToGen; i++)
            {
                var tmp = tmpList[i];
                Assert.AreEqual(_Context.TemplateControls.OrderByDescending(x => x.Id).Skip(noToGen - i - 1).First().Id, tmp.Id);
                Assert.AreEqual(_TestTemplateControlTypes[i % _TestTemplateControlTypes.Count].AdminDisplayControlType, tmp.AdminDisplayControlType);
                Assert.AreEqual(_TestTemplateControlTypes[i % _TestTemplateControlTypes.Count].AdminEditControlType, tmp.AdminEditControlType);
                Assert.AreEqual(_TestTemplateControlTypes[i % _TestTemplateControlTypes.Count].FrontEndControlType, tmp.FrontEndControlType);
                Assert.AreEqual(_TestTemplateControlTypes[i % _TestTemplateControlTypes.Count].Name, tmp.TemplateControlTypeName);
                Assert.AreEqual(_TestTemplateControlTypes[i % _TestTemplateControlTypes.Count].Id, tmp.TemplateControlTypeId);
                Assert.AreEqual("Insert Name {0}".Format(i), tmp.Name);
                Assert.AreEqual("Insert Notes {0}".Format(i), tmp.Notes);
                Assert.AreEqual(_Context.TemplateControls.OrderByDescending(x => x.Id).Skip(noToGen - i - 1).First().CID, tmp.CID);
                Assert.AreEqual(i, tmp.Sequence);
                Assert.AreEqual(_TestTemplates[1].Id, tmp.TemplateId);
            }

            var tmpList2 = factory.GetAllByTemplateId(_TestTemplates[1].Id).ToList();
            for (int i = 0; i < noToGen; i++)
            {
                var tmp = tmpList[i];
                var tmp2 = tmpList2.Find(x => x.Id == tmp.Id);
                Assert.AreEqual(tmp2.Id, tmp.Id);
                Assert.AreEqual(tmp2.AdminDisplayControlType, tmp.AdminDisplayControlType);
                Assert.AreEqual(tmp2.AdminEditControlType, tmp.AdminEditControlType);
                Assert.AreEqual(tmp2.FrontEndControlType, tmp.FrontEndControlType);
                Assert.AreEqual(tmp2.Name, tmp.Name);
                Assert.AreEqual(tmp2.Notes, tmp.Notes);
                Assert.AreEqual(tmp2.CID, tmp.CID);
                Assert.AreEqual(tmp2.Sequence, tmp.Sequence);
                Assert.AreEqual(tmp2.TemplateControlTypeName, tmp.TemplateControlTypeName);
                Assert.AreEqual(tmp2.TemplateControlTypeId, tmp.TemplateControlTypeId);
                Assert.AreEqual(tmp2.TemplateId, tmp.TemplateId);

            }
        }

        [TestMethod]
        public void TemplateControl_Insert_SeqeuenceTest()
        {
            TemplateControlFactory factory = new TemplateControlFactory(_Context);
            var tmp = new TemplateControl(_TestTemplates[0].Id);
            tmp.TemplateControlTypeId = _TestTemplateControlTypes[0].Id;
            tmp.Name = "SeqeunceTest";
            tmp.Notes = "SeqeunceTest";
            factory.Save(tmp);
            Assert.AreEqual(_TestTemplateControls.Count(), tmp.Sequence);
            var tmp2 = factory.GetAllByTemplateId(_TestTemplates[0].Id).ToList();
            Assert.AreEqual(tmp2.Last().Id, tmp.Id);

        }

        [TestMethod]
        [ExpectedException(typeof(Bll.Exceptions.ValidationException))]
        public void TemplateControl_NoName_ThrowsException()
        {
            TemplateControlFactory factory = new TemplateControlFactory(_Context);
            var tmp = new TemplateControl(_TestTemplates[0].Id);

            tmp.TemplateControlTypeId = _TestTemplateControls[0].Id;
            tmp.Notes = "Insert Notes";

            factory.Save(tmp);
        }

        [TestMethod]
        [ExpectedException(typeof(Bll.Exceptions.ValidationException))]
        public void TemplateControl_NoTemplateControlTypeId_ThrowsException()
        {
            TemplateControlFactory factory = new TemplateControlFactory(_Context);
            var tmp = new TemplateControl(_TestTemplates[0].Id);

            tmp.Name = "Test";
            tmp.Notes = "Insert Notes";

            factory.Save(tmp);
        }

        [TestMethod]
        [ExpectedException(typeof(Bll.Exceptions.ValidationException))]
        public void TemplateControlType_NoTemplateId_ThrowsException()
        {
            TemplateControlFactory factory = new TemplateControlFactory(_Context);
            var tmp = new TemplateControl(0);

            tmp.TemplateControlTypeId = _TestTemplateControls[0].Id;
            tmp.Name = "Test";
            tmp.Notes = "Insert Notes";

            factory.Save(tmp);
        }

        [TestMethod]
        public void TemplateControlType_Move()
        {
            TemplateControlFactory factory = new TemplateControlFactory(_Context);
            var tmp = factory.GetAllByTemplateId(_TestTemplates[0].Id).ToList();
            
            factory.Move(tmp, 1, 0);

            Assert.AreEqual(_TestTemplates[1].Id, tmp[0].Id);
            Assert.AreEqual(0, tmp[0].Sequence);
            Assert.AreEqual("Template Control 1", tmp[0].Name);

            Assert.AreEqual(_TestTemplates[0].Id, tmp[1].Id);
            Assert.AreEqual(1, tmp[1].Sequence);
            Assert.AreEqual("Template Control 0", tmp[1].Name);
        }

        [TestMethod]
        public void TemplateControlType_Swap()
        {
            TemplateControlFactory factory = new TemplateControlFactory(_Context);
            var tmp = factory.GetAllByTemplateId(_TestTemplates[0].Id).ToList();
            int a = 0;
            int b = 3;
            factory.Swap(tmp, a, b);

            Assert.AreEqual(_TestTemplateControls[b].Id, tmp[a].Id);
            Assert.AreEqual(a, tmp[a].Sequence);
            Assert.AreEqual("Template Control {0}".Format(b), tmp[a].Name);

            Assert.AreEqual(_TestTemplateControls[a].Id, tmp[b].Id);
            Assert.AreEqual(b, tmp[b].Sequence);
            Assert.AreEqual("Template Control {0}".Format(a), tmp[b].Name);
        }

    }
}
